package top.codedance.iotp.common.util.db.mysql;

import org.apache.log4j.Logger;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

public class ConnectionPool {
    private static Logger logger = Logger.getLogger(ConnectionPool.class);

    private List<Connection> cs = new ArrayList<>();
    private Properties properties;
    private static Class<?> clazz;
    private String jdbcUrl;
    private String user;
    private String password;
    private int size;
    private int initCount;

    public ConnectionPool(Class<?> clazz, Logger logger, Properties properties) {
        this.logger = logger;
        this.clazz = clazz;
        this.properties = properties;
        if (properties != null) {
            if (properties.containsKey("poolMaxSize")) {
                this.size = Integer.valueOf(properties.getProperty("poolMaxSize"));
            }
            if (properties.containsKey("poolMinSize")) {
                this.initCount = Integer.valueOf(properties.getProperty("poolMinSize"));
            }
            if (properties.containsKey("jdbcUrl")) {
                this.jdbcUrl = properties.getProperty("jdbcUrl");
            } else {
                this.jdbcUrl = null;
            }
            if (properties.containsKey("user")) {
                this.user = properties.getProperty("user");
            } else {
                this.user = null;
            }
            if (properties.containsKey("password")) {
                this.password = properties.getProperty("password");
            } else {
                this.password = null;
            }
        } else {
            logger.info("database parameters is empty.");
        }
        init();
    }

    private void createConnect() {
        try {
            if (this.properties != null && this.jdbcUrl != null) {
                Class.forName("com.mysql.cj.jdbc.Driver");
                Connection c = DriverManager.getConnection(this.jdbcUrl, this.user, this.password);
                logger.debug("Connecting " + cs.size() + " connection.");
                cs.add(c);
            } else {
                logger.info("database parameters is empty.");
            }
        } catch (Exception e) {
            logger.info("database init fail.");
            try {
                Thread.sleep(1000);
            }catch (Exception ex){}
        }
    }

    private void init() {
        for (int i = 0; i < initCount; i++) {
            createConnect();
        }
    }

    public synchronized Connection getConnection() throws InterruptedException {
        Connection c = null;
        while (true) {
            while (cs.isEmpty()) {
                if(this.initCount < this.size){
                    createConnect();
                }else{
                    this.wait();
                }
            }
            c = cs.remove(0);
            try {
                Statement statement = c.createStatement();
                statement.execute("SELECT 'AA'");
                statement.close();
                break;
            } catch (SQLException ex) {
                logger.debug("Connection is timeout, reconnecting...");
            }
        }
        return c;
    }

    public synchronized void returnConnection(Connection c) {
        try {
            Statement statement = c.createStatement();
            statement.execute("SELECT 'AA'");
            statement.close();
            //使用完给回连接池中
            cs.add(c);
            //唤醒wait告诉它有新的连接池可用
            this.notifyAll();
        } catch (SQLException ex) {ex.printStackTrace();}
    }
}
